#ifndef VOIP_RS_THREAD_H_
#define VOIP_RS_THREAD_H_

//author : shike@outlook.com
//  date : 2013/07/03
// brief : cctalk voip engine recv/send thread

#include "ct_udp_socket.h"
#include "ct_udp_msg_buf.h"
#include "ct_voip_channel.h"
#include "ctRWLock.h"
#include "ct_voip_msg_cache_mgr.h"
#include "ct_voip_lost_checker_mgr.h"
#include <map>


class ctVOIPChannel;
class ctVOIPThreadPool;
namespace AudioCmd {
        class stUDPForwardRoom;
        class stUDPForwardRoomNew;
        class stUDPForwardRoomNewNew;
}
class ctVOIPRSThread:
        public ctThread
{
        public:
                ctVOIPRSThread(ctVOIPThreadPool *pool, const eUDPProtoType &type);
                ~ctVOIPRSThread();
                bool init(const std::string &ip, const WORD &port);

                void addChannel(const DWORD &channelid);
                void delChannel(const DWORD &channelid);
                void addWaitUser(const DWORD &channelid, const DWORD &userid);
                void delWaitUser(const DWORD &channelid, const DWORD &userid);
                void delUser_app(const DWORD &channelid, const DWORD &userid);
                bool addUser(const DWORD &channelid, const DWORD &userid, struct sockaddr_in &addr);
                void delUser(const DWORD &channelid, const DWORD &userid);
                void disableMediaData(uint32_t room_id, uint32_t user_id, uint8_t type, bool enable);
                void updateUserAddr(const DWORD &channelid, const DWORD &userid, struct sockaddr_in &addr);
                void addSpeakUser(const DWORD &channelid, const DWORD &userid);
                void delSpeakUser(const DWORD &channelid, const DWORD &userid);
                void setResetData();
                void resetData();

        private:
                void run();
                void recvData();
                void sendData();
                void copyDataToRelay();
                void copyDataFromRelay();
                void processData();
                void checkPacketLost(AudioCmd::stUDPForwardRoom* rev);
                void checkPacketLost(AudioCmd::stUDPForwardRoomNew* rev);
                void checkPacketLost(AudioCmd::stUDPForwardRoomNewNew* rev);
                void cacheSendPacket(const BYTE* packet, DWORD length);
                bool isSpeakUser(const DWORD &roomid, const DWORD &userid);
                void clearChannels();
                void clearSpeakUsers();

                Channel *getChannel(const DWORD &channelid);

        private:
                ctVOIPThreadPool *pool_;
                eUDPProtoType type_;
                ctUDPSocket udp_socket_;

                std::map<DWORD, Channel *> channels_;
                ctRWLock rwlock_channel_;

                std::map<DWORD, DWORD> speak_users_;
                ctRWLock rwlock_speak_;

                t_BufferCmdQueue snd_queue_;
                t_BufferCmdQueue rcv_queue_;

                bool reset_data_;

                // packet lost checker for: client->server packets.
                ctVOIPLostCheckerMgr    audio_lost_checker_;
                ctVOIPLostCheckerMgr    video_lost_checker_;

                //cache for: server->client packets.
                ctVOIPMsgCacheMgr       audio_send_cache_;
                ctVOIPMsgCacheMgr       video_send_cache_;

                Timer                   one_min_timer_;
};

#endif //VOIP_RS_THREAD_H_
